package com.zhupf.queue;

import java.util.Deque;
import java.util.LinkedList;

/**
 * @author zhupf
 * @date 2025年01月07日 11:00
 * @Description 1425. 带限制的子序列和
 * 给你一个整数数组 nums 和一个整数 k ，请你返回 非空 子序列元素和的最大值，子序列需要满足：子序列中每两个 相邻 的整数 nums[i] 和 nums[j] ，它们在原数组中的下标 i 和 j 满足 i < j 且 j - i <= k 。
 * <p>
 * 数组的子序列定义为：将数组中的若干个数字删除（可以删除 0 个数字），剩下的数字按照原本的顺序排布。
 * <p>
 * <p>
 * <p>
 * 示例 1：
 * <p>
 * 输入：nums = [10,2,-10,5,20], k = 2
 * 输出：37
 * 解释：子序列为 [10, 2, 5, 20] 。
 * 示例 2：
 * <p>
 * 输入：nums = [-1,-2,-3], k = 1
 * 输出：-1
 * 解释：子序列必须是非空的，所以我们选择最大的数字。
 * 示例 3：
 * <p>
 * 输入：nums = [10,-2,-10,-5,20], k = 2
 * <p>
 * 输出：23
 * 解释：子序列为 [10, -2, -5, 20] 。
 */
public class ConstrainedSubsetSum {
    public static void main(String[] args) {
        int[] nums = {10,-2,-10,-5,20};
        System.out.println(constrainedSubsetSum(nums, 2));
    }

    public static int constrainedSubsetSum(int[] nums, int k) {
        Deque<Integer> deque = new LinkedList<>();
        int[] dp = new int[nums.length];
        deque.offerLast(0);
        dp[0] = nums[0];
        int sum = nums[0];
        for (int i = 1; i < nums.length; i++) {
            if (!deque.isEmpty() && i - deque.peekFirst() > k) {
                deque.pollFirst();
            }
            dp[i] = Math.max(nums[i], nums[i] + dp[deque.peekFirst()]);
            sum = Math.max(sum, dp[i]);
            while (!deque.isEmpty() && dp[i] > dp[deque.peekLast()]) {
                deque.pollLast();
            }
            deque.offerLast(i);
        }
        return sum;

    }

}
